package com.qbb.server.aop;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.netty.server.QbbSocketServer;
import com.qbb.server.aop.annotation.QbbServer;
import com.qbb.server.aop.bean.MethodConsBean;
import com.qbb.server.aop.collection.ConnsTypeUtil;
import com.qbb.server.aop.enums.QbbConnsTypeEnum;
import com.qbb.server.aop.enums.StatuEnum;
import com.qbb.server.bean.read.SocketBean;
import com.qbb.server.bean.result.SocketResultBean;
import com.qbb.server.bean.result.SocketResultMapBean;
import com.qbb.server.exception.HandlerException;
import com.qbb.server.util.DateUtil;

/**
 * 类说明
 * 
 * @author chenhuaiao
 * @version V1.0 创建时间：Mar 16, 2015 5:46:58 PM
 */
public class QbbServerAopUtil {
	private static Log log = LogFactory.getLog(QbbServerAopUtil.class);

	/**
	 * 服务端解析调用的服务方法,返回结果
	 * 
	 * @param socketBean
	 * @return
	 */
	public static SocketResultBean getResult(SocketBean socketBean) {
		SocketResultBean returnBean = new SocketResultMapBean();

		String annModelName = null;
		String annOptionName = null;

		try {
			String modelName = socketBean.getModel();
			String methodName = socketBean.getMethod();
			Object paramObj = socketBean.getParams();

			if (modelName == null) {
				returnBean.setErrorMsg("客户端传入的modelName为空");
				return returnBean;
			}

			if (methodName == null) {
				returnBean.setErrorMsg("客户端传入的methodName为空");
				return returnBean;
			}
			Object modelBean = QbbSocketServer.application.getBean(modelName);

			Class beanClass = modelBean.getClass();

			MethodConsBean consBean = JavassistUtil.getMethodConsBean(
					beanClass, methodName);
			QbbServer myAnnotation = consBean.getMyAnnotation();
			if (myAnnotation == null) {
				returnBean.setErrorMsg("服务端定义的接口方法,没有声明注解@QbbServer");
				return returnBean;
			}
			StatuEnum statuEnum = myAnnotation.statu();
			if (statuEnum == StatuEnum.DISENABLE) {
				returnBean.setErrorMsg("服务端定义的接口方法,注解@QbbServer的状态是禁用的");
				return returnBean;
			}

			annModelName = myAnnotation.moduleName();
			annOptionName = myAnnotation.option();

			Class[] inTypeArray = consBean.getInTypes();
			int inTypeArrayLen = inTypeArray != null ? inTypeArray.length : 0;

			String[] inTypeNameArray = consBean.getInNames();

			Method method = beanClass
					.getDeclaredMethod(methodName, inTypeArray);
			// 方法的参数是大于2个时，默认的参数结果集是Map类型的
			Object[] invokeParams = null;

			if (inTypeArrayLen >= 2) {
				invokeParams = new Object[inTypeArrayLen];
				getParamByMap(inTypeArray, paramObj, inTypeArrayLen,
						inTypeNameArray, invokeParams);
			} else if (inTypeArrayLen == 1) {
				invokeParams = new Object[1];

				String className = inTypeArray[0].getName();
				// 不是List ,Set , Map这类参数
				if (ConnsTypeUtil.getType(className).equals(
						QbbConnsTypeEnum.OTHER)) {
					getParamByMap(inTypeArray, paramObj, inTypeArrayLen,
							inTypeNameArray, invokeParams);
				} else {
					invokeParams[0] = paramObj;
				}
			}

			Object methodResultData = null;

			Class outTypeClass = consBean.getOutType();
			try {
				long invokebegin = System.currentTimeMillis();
				if (outTypeClass != null) {
					if (invokeParams != null) {
						methodResultData = method.invoke(modelBean,
								invokeParams);
					} else {
						methodResultData = method.invoke(modelBean);
					}
				} else {
					if (invokeParams != null) {
						method.invoke(modelBean, invokeParams);
					} else {
						method.invoke(modelBean);
					}
				}
				long invokeend = System.currentTimeMillis();
				Double invokeTime = (invokeend - invokebegin) / 1000.00;

				String infoSql = "QbbServer--execute--server[" + modelName
						+ "],method[" + methodName + "]" + "共耗时[" + invokeTime
						+ "]秒";

				log.info(infoSql);
			} catch (Exception invokeEx) {
				HandlerException.error(invokeEx);
				returnBean.setErrorMsg("服务端动态调用服务接口存在异常信息");
				return returnBean;
			}
			String resultClazType = methodResultData.getClass().getName();
			QbbConnsTypeEnum typeEnum = ConnsTypeUtil.getType(resultClazType);

			if (typeEnum.equals(QbbConnsTypeEnum.Map)) {
				returnBean.setResult(methodResultData);
			}

		} catch (Exception e) {
			HandlerException.error(e);
			returnBean.setErrorMsg("服务端动态调用服务接口存在异常信息");
			return returnBean;
		} finally {
			if (returnBean == null) {
				returnBean = new SocketResultBean();
			}
		}
		return returnBean;
	}

	private static void getParamByMap(Class[] inTypeArray, Object paramObj,
			int inTypeArrayLen, String[] inTypeNameArray, Object[] invokeParams) {
		Map<String, Object> resultMap = (Map<String, Object>) paramObj;
		for (int i = 0; i < inTypeArrayLen; i++) {
			String name = inTypeNameArray[i];
			Object result = resultMap.get(name);
			Class fromClass = result.getClass();
			Class toClass = inTypeArray[i];
			invokeParams[i] = ConnsTypeUtil.parse(fromClass, toClass, result);
		}
	}
}
